/*
* Copyright 2016 SAIC-GM Corporation Ltd. All Rights Reserved.
*
* This software is published under the terms of the SAIC-GM Software
* License version 1.0, a copy of which has been included with this
* distribution in the LICENSE.txt file.
*
* @Project         marketing

* @Package         com.yonyou.marketing.wechat.entrance

* @Author          LuZhen

* @FileName        WeChatMessageContoller

* @Date            2016/12/19

----------------------------------------------------------------------------------
*     Date          Who             Version         Comments
* 1. 2016/12/19        LuZhen          1.0             Create Source
*
----------------------------------------------------------------------------------
*/
package com.yonyou.gmmc.service.wechatpush.controller;

import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.yonyou.gmmc.service.wechatpush.common.WechatDict;
import com.yonyou.gmmc.service.wechatpush.dto.WxGzMessageDto;
import com.yonyou.gmmc.service.wechatpush.mq.entrance.MessageReceiver;
import com.yonyou.gmmc.service.wechatpush.provider.PushThreadCallable;
import com.yonyou.gmmc.service.wechatpush.provider.PushThreadCallback;
import com.yonyou.gmmc.service.wechatpush.resolver.MessageResolver;
import com.yonyou.gmmc.service.wechatpush.resolver.PushMessage;
import com.yonyou.gmmc.service.wechatpush.service.TokenService;
import com.yonyou.gmmc.service.wechatpush.service.WechatMessageService;
import com.yonyou.gmmc.service.wechatpush.util.HttpUtil;
import com.yonyou.gmmc.service.wechatpush.util.WechatMessageHandleUtils;

import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONObject;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.marketing.common.constants.CookieConstant;
import org.marketing.common.constants.MessagePushConstant;
import org.marketing.common.entity.Check;
import org.marketing.common.entity.wechatpushmessage.WeChatMessageProtocol;
import org.marketing.common.entity.wechatpushmessage.WeChatMessageProtocolHandleInfo;
import org.marketing.common.util.CheckUtil;
import org.marketing.common.util.CookieSecurityUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.expression.ParseException;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class WeChatMessageController {

	private static Logger logger = Logger.getLogger(MessageReceiver.class);

	@Autowired
	private MessageResolver messageResolver;

	@Autowired
	private ApplicationContext context;

	@Autowired
	private ListeningExecutorService executorService;

	@Autowired
	private WechatMessageService wechatMessageService;

	@Autowired
	private TokenService tokenService;

	// 微信验证服务器回调接口
	@RequestMapping(value = "/wechatcall/request", method = RequestMethod.GET) // ,
																				// produces="text/html;charset=UTF-8"
	@ResponseBody
	public String validateGet(Check tokenModel, HttpServletRequest req, HttpServletResponse res)
			throws ParseException, IOException {
		logger.info("----WeChatMessageController,get,check");
		// 代码扫描 1533
		Check check = new Check();
		check.setEchostr(tokenModel.getEchostr());
		check.setErrcode(tokenModel.getErrcode());
		check.setErrmsg(tokenModel.getErrmsg());
		check.setNonce(tokenModel.getNonce());
		check.setSignature(tokenModel.getSignature());
		check.setTimestamp(tokenModel.getTimestamp());
		// 2017-09-25 代码扫描（Cross-Site Scripting: Reflected）
		String wxToken = WechatDict.token.replaceAll("\\\\", "");
		String regEx = "[|&;$%@'\"<>()+,.]";
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(wxToken);
		wxToken = m.replaceAll("").trim();
		wxToken = wxToken.replaceAll("CR", "").replaceAll("LF", "").replaceAll("script", "").replaceAll("document", "")
				.replaceAll("eval", "");

		String validate = wechatMessageService.validate(wxToken, check);
		logger.info("---" + validate);
		return validate;
	}

	/**
	 * @author LiuJun 接收经销商公众号消息入口
	 * @date 2016年12月6日
	 * @param openId
	 * @param nonce
	 * @param timestamp
	 * @param signature
	 * @param xml
	 * @return
	 */// @RequestBody Map<String, String> map,
	@RequestMapping(value = "/wechatcall/request", method = RequestMethod.POST) // ,
																				// produces
																				// =
																				// "text/plain;charset=UTF-8"
	@ResponseBody
	public String receiveDealerWeChatMsg(HttpServletRequest req, HttpServletResponse rps, @RequestBody String xml)
			throws Exception {
		// logger.info("----WeChatMessageController,post," + xml);
		// String returnMsg =
		// wechatMessageService.receiveAndReplyDealerWeChatMsg(dealerAppid,nonce,timestamp,signature,xml);
		logger.info("微信推送消息为：" + xml);
		Map<String, String> xmlMap = WechatMessageHandleUtils.xmlToMap(xml);
		String msgType = xmlMap.get("MsgType");
		String returnMsg = "";
		String openid = req.getParameter("openid");
		writeWechatCookiesInfo(openid, rps, req);
		if (WechatDict.MESSAGE_TYPE_EVENT.equals(msgType)) {
			logger.info("进入关注事件");
			returnMsg = wechatMessageService.receiveAndReplyDealerWeChatMsg(xml, rps, req);
			return returnMsg;
		} else if (WechatDict.MESSAGE_TYPE_TEXT.equals(msgType)) {
			int flag = wechatMessageService.confirmService(xml);
			if (flag == 0) {
				logger.info("进入在线客服服务！");
				returnMsg = wechatMessageService.receiveMsg(xml, rps, req);
			} else if (flag == 1) {
				logger.info("智能回复匹配！");
				returnMsg = wechatMessageService.receiveAndReplyDealerWeChatMsg(xml, rps, req);
			} else if (flag == 2) {
				logger.info("等待转接在线客服！");
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("ToUserName", xmlMap.get("FromUserName"));
				map.put("FromUserName", xmlMap.get("ToUserName"));
				map.put("CreateTime", new Date().getTime() + "");
				map.put("MsgType", WechatDict.MESSAGE_TYPE_TEXT);
				map.put("Content", "请输入您的问题，我们将帮您转接在线客服！");
				returnMsg = WechatMessageHandleUtils.mapToXml(map);
			} else {
				logger.info("服务异常！");
				Map<String, Object> map = new HashMap<String, Object>();
				map.put("ToUserName", xmlMap.get("FromUserName"));
				map.put("FromUserName", xmlMap.get("ToUserName"));
				map.put("CreateTime", new Date().getTime() + "");
				map.put("MsgType", WechatDict.MESSAGE_TYPE_TEXT);
				map.put("Content", "网络异常，请稍后重新尝试！");
				returnMsg = WechatMessageHandleUtils.mapToXml(map);
			}
		} else {
			logger.info("进入在线客服服务！");
			returnMsg = wechatMessageService.receiveMsg(xml, rps, req);
		}
		return returnMsg;
	}

	@RequestMapping(value = "/genToken", method = RequestMethod.GET)
	@ResponseBody
	public String genToken() {
		Map<String, String> map = new HashMap<String, String>();
		String tmp = tokenService.genAccessToken();
		map.put("token", tmp);
		map.put("name", "success");
		logger.info("--genToken:" + tmp);
		JSONObject obj = JSONObject.fromObject(map);
		return obj.toString();
	}

	@RequestMapping(value = "/wechat-push/api/v1/replyUser", method = RequestMethod.POST)
	@ApiOperation(value = "客服回复用户消息", notes = "客服回复用户消息")
	@ResponseBody
	public Map<String, Object> replyMsgToUser(@RequestBody WxGzMessageDto wxGzMessageDto) throws Exception {
		Map<String, Object> result = new HashMap<String, Object>();
		try {
			String token = tokenService.genAccessToken();
			result = wechatMessageService.replyMsgToUser(wxGzMessageDto, token);
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		return result;
	}

	@RequestMapping(value = "/wechat-push/api/v1/disconnect", method = RequestMethod.GET)
	@ApiOperation(value = "断开微信用户与客服的连接", notes = "断开微信用户与客服的连接")
	@ResponseBody
	public Map<String, Object> disconnect(@RequestParam("openId") String openId) throws Exception {
		Map<String, Object> result = new HashMap<String, Object>();
		try {
			result = wechatMessageService.disconnect(openId);
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		return result;
	}

	@RequestMapping(value = "/wechat-push/api/v1/sendTextMsg/{openId}/{content}", method = RequestMethod.GET)
	@ResponseBody
	public Map<String, Object> sendTextMsg(@PathVariable("openId") String openId,
			@PathVariable("content") String content) {

		Map<String, Object> resultMap = new HashMap<String, Object>();

		try {
			String token = genToken();
			JSONObject json = JSONObject.fromObject(token);

			if (token == null || "".equals(token.trim()))
				throw new Exception("");

			String url = WechatDict.sendTxtMessageUrl.replace("ACCESS_TOKEN", json.getString("token"));

			logger.info("--------------------发送客服消息请求的URL:" + url);

			String param = "{\"touser\":\"" + openId + "\",\"msgtype\":\"text\",\"text\":{\"content\":\"" + content
					+ "\"}}";

			String message = HttpUtil.post(url, param);

			resultMap.put("STATUS", "0");
			resultMap.put("MESSAGE", message);
		} catch (Exception e) {
			resultMap.put("STATUS", "1");
			resultMap.put("MESSAGE", e.getMessage());
		}
		return resultMap;
	}

	@RequestMapping(value = "/wechat-push/api/v1/user/{openid}", method = RequestMethod.GET)
	@ResponseBody
	public String getUserByopenid(@PathVariable("openid") String openid) {

		// 2017-09-25 代码扫描（Cross-Site Scripting: Reflected）
		openid = openid.replaceAll("\\\\", "");
		String regEx = "[|&;$%@'\"<>()+,.]";
		Pattern p = Pattern.compile(regEx);
		Matcher m = p.matcher(openid);
		openid = m.replaceAll("").trim();
		openid = openid.replaceAll("CR", "").replaceAll("LF", "").replaceAll("script", "").replaceAll("document", "")
				.replaceAll("eval", "");

		return wechatMessageService.getUser(openid);
	}

	/*
	 * @RequestMapping(value = "/wechatcall/test", method = RequestMethod.GET)
	 * // , produces="text/html;charset=UTF-8"
	 * 
	 * @ResponseBody public String validateTest(Check tokenModel,
	 * HttpServletRequest req, HttpServletResponse res) throws ParseException,
	 * IOException { logger.info("---test,user=" + req.getHeader("user"));
	 * 
	 * return "helloword"; }
	 */

	private void writeWechatCookiesInfo(String openid, HttpServletResponse response, HttpServletRequest req) {
		try {
			String userId = selectUserIdByOpenId(openid);
			logger.info("需要将UserID写入Cookie");
			Cookie UserIdcookies = new Cookie(CookieConstant.WECHAT_COOKIE_USERID, CookieSecurityUtil.encrypt(userId));
			UserIdcookies.setMaxAge(30 * 60);
			UserIdcookies.setPath("/");
//			UserIdcookies.setDomain("carowner.yonyouauto.com");
			response.addCookie(UserIdcookies);
			Cookie cookies = new Cookie(CookieConstant.WECHAT_COOKIE_OPENID, CookieSecurityUtil.encrypt(openid));
			cookies.setMaxAge(30 * 60);
			cookies.setPath("/");
//			cookies.setDomain("carowner.yonyouauto.com");
			response.addCookie(cookies);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	@RequestMapping(value = "/wechat-push/api/v1/userId", method = RequestMethod.GET)
	@ResponseBody
	public String selectUserIdByOpenId(@RequestParam("openid") String openid) {
		String userId = "";
		userId = wechatMessageService.selectUserIdByOpenId(openid);
		return userId;
	}

	// @RequestMapping(value = "/wechatcall/request",method =
	// RequestMethod.POST,consumes =
	// MediaType.APPLICATION_JSON_UTF8_VALUE)
	public void receiveMessage(@RequestBody WeChatMessageProtocol protocol) {
		logger.debug("protocol is " + protocol);
		// 获取处理信息
		WeChatMessageProtocolHandleInfo newHandleInfo = WeChatMessageProtocolHandleInfo.init(protocol.getHandleInfo());
		protocol.setHandleInfo(newHandleInfo);
		// 丢弃消息
		if (newHandleInfo.isDeprive()) {
			// logger.error("deprive message " + protocol);
			return;
		}
		// 转换为协议消息
		PushMessage pushMessage = messageResolver.receiveMessage(protocol);
		// 验证协议消息
		if (!messageResolver.validateMessage(pushMessage)) {
			logger.error("message validate error");
			return;
		}
		// 转入发送线程
		PushThreadCallable pushThreadCallable = context.getBean(MessagePushConstant.PROVIDER_THREAD,
				PushThreadCallable.class);
		pushThreadCallable.setProviderMessage(pushMessage);
		PushThreadCallback pushThreadCallback = context.getBean(PushThreadCallback.class, protocol);
		Futures.addCallback(executorService.submit(pushThreadCallable), pushThreadCallback);
	}

	@RequestMapping(value = "/test", method = RequestMethod.GET, produces = "application/json;charset=UTF-8")
	@ApiOperation(value = "测试接口", notes = "测试接口")
	public void test() {
		// String openId = "oXrcfuGP_a3daNZaMT_rbhvJ595I";
		// logger.info("传入的OPEN_ID为:"+openId);
		//// WeChatMessageProtocol
		// t=wechatMessageService.sendInsuranceExpire(openId);
		//// logger.info("返回值为:"+t);
		//// this.sendNotify(t);
		// String mediaId1 =
		// "2DfUuYa0JKGSVbJNgzzR_VA--HpbN8LS0AQSH95ONJ23spftA3tUmriY4FF2lPhT";
		// String mediaId2 =
		// "biVfNWVJt0QQ3cD0TJHcrR69142AZjrsusJSlQfgKYqRybw1yHuMQgZgoqF6q_pr";
		// String mediaId3 =
		// "_UM2MCnSBGiAoeb3I1FKp7tozCIObRPAH-HgG7DlIaGDzMaMSP3NNash9qxiDTTU";
		// List<String> list = new ArrayList<String>();
		// list.add(mediaId1);
		// list.add(mediaId2);
		// list.add(mediaId3);
		// List<String> s = DloadImgUtil.downloadMedia(list);
		// logger.info("返回结果："+s.size());
	}

	@RequestMapping(value = "/Token", method = RequestMethod.GET)
	@ResponseBody
	@ApiOperation(value = "其他微服务获取TOKEN", notes = "其他微服务获取TOKEN")
	public String Token() {
		String token = tokenService.getAccessToken();
		return token;
	}
}
